﻿using System;
using System.Windows.Forms;
using PluginInterface;
using System.Drawing;
using Qurihara;
using System.Reflection;
using System.IO;
using Qurihara.QBasic;
using System.Threading;
using System.Collections;

using System.Collections.Generic;
using Qurihara.OSCCom;

using System.Deployment.Application;
using System.Collections.Specialized;
using System.Web;

namespace KotodamaPlugin.ManagerPlugin
{
	/// <summary>
	/// Class1 の概要の説明です。
	/// </summary>
	public class ManagerPlugin :IPlugin
    {
        private System.Windows.Forms.Timer timer;
        Qurihara.OSCCom.IComCore core;
        Qurihara.OSCCom.ComForDisplay com;

        TabControl tabControlMembers;
        List<string> highlightList = new List<string>();

		public ManagerPlugin()
		{
		}


		#region IPlugin Members
		
		IPluginHost myPluginHost = null;
		string myPluginName = "Manager Plugin";
		string myPluginAuthor = "K.Qurihara";
		string myPluginDescription = "test plugin";
		string myPluginVersion = "1.0.0";
		
		public void Initialize()
		{
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                NameValueCollection query = new NameValueCollection();
                string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query;
                query = HttpUtility.ParseQueryString(queryString);

                //managerなし連動
                string sync = query["sync"];
                //groupとname
                string group = query["group"];
                string name = query["name"];

                if (sync != null && sync == "true")
                {
                    core = new Qurihara.OSCCom.SyncWebComCore();
                }
                else
                {
                    core = new Qurihara.OSCCom.WebComCore();
                }
                if (name != null && name != "")
                    core.Name = name;
                if (group != null && group != "")
                    ((Qurihara.OSCCom.WebComCore)core).GroupName = group;
            }
            else
            {
                core = new Qurihara.OSCCom.SyncWebComCore(); // TODO: ローカル起動したときにどうするかを決める
                //core = new Qurihara.OSCCom.TCPComCore();
            }
            //com = new Qurihara.OSCCom.ComForManager(Host.Kotodama, core);
            com = new Qurihara.OSCCom.ComForDisplay(Host.Kotodama,core);
            com._manager = true;

            timer = new System.Windows.Forms.Timer();
            timer.Interval = 500;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Enabled = true;
            timer.Start();
            //InitOSC();
            com.Initialize();//Host.Kotodama);
            //AskId(com.Name);


            com.ViewMovedReceived += new ComForDisplay.ViewMovedReceivedEventHandler(com_ViewMovedReceived);
            com.StrokeElementListCreated += new ComForDisplay.StrokeElementListCreatedEventHandler(com_StrokeElementListCreated);
            com.NewPersonalInkNameReveived += new ComForDisplay.NewPersonalInkNameReceivedEventHandler(com_NewPersonalInkNameReveived);
            Control c = (Control)Host.Kotodama.EnvironmentTable["Base.Form"];
            Control[] cld = c.Controls.Find("tabControlMembers", true);
            tabControlMembers = (TabControl)cld[0];
            tabControlMembers.Selected += new TabControlEventHandler(tcM_Selected);

            Control[] cld2 = c.Controls.Find("listViewScreens", true);
            ListView lvS = (ListView)cld2[0];
            lvS.SelectedIndexChanged += new EventHandler(lvS_SelectedIndexChanged);

            Host.Kotodama.Presentation.CurrentSlide.View.ViewChanged += new EventHandler(View_ViewChanged);

		}

		void PluginInterface.IPlugin.Dispose()
		{
            timer.Stop();
            timer.Enabled = false;
            timer.Dispose();
            com.Dispose();

		}

		#region misc.
		public string Description
		{
			get
			{
				// TODO:  Add ctlMain.Description getter implementation
				return myPluginDescription;
			}
		}

		public string Author
		{
			get
			{
				// TODO:  Add ctlMain.Author getter implementation
				return myPluginAuthor;
			}
		}

		public IPluginHost Host
		{
			get
			{
				// TODO:  Add ctlMain.Host getter implementation
				return myPluginHost;
			}
			set
			{
				myPluginHost = value;
			}
		}

		
		public string Name
		{
			get
			{
				// TODO:  Add ctlMain.Name getter implementation
				return myPluginName;
			}
		}
		

		public string Version
		{
			get
			{
				// TODO:  Add ctlMain.Version getter implementation
				return myPluginVersion;
			}
		}
		#endregion

		#endregion

        void timer_Tick(object sender, EventArgs e)
        {
            Control c = (Control)Host.Kotodama.EnvironmentTable["Base.Form"];
            string t = c.Text;
            string[] ts = t.Split('@');
            string title = ts[0];
            if (core == null)
            {
                Delegate d = (MethodInvoker)delegate()
                {
                    c.Text = title + "@初期化中";
                };
                Host.Kotodama.Control.BeginInvoke(d);
            }
            else
                if (core.IsConnected)
                {
                    Delegate d = (MethodInvoker)delegate()
                    {
                        c.Text = title + "@接続中";
                    };
                    Host.Kotodama.Control.BeginInvoke(d);
                }
                else
                {
                    Delegate d = (MethodInvoker)delegate()
                    {
                        c.Text = title + "@非接続";
                    };
                    Host.Kotodama.Control.BeginInvoke(d);
                }

            //タブのハイライトも500ms単位。
            TickHighlight();
        }


        #region tab系
        //state:personalの実験はしていない。特殊なタブの処理も増やさないといけない
        void tcM_Selected(object sender, TabControlEventArgs e)
        {
            // タブが選択された --> 描画パネルの移動。特殊なタブなら処理をする。
            MovePanelCanvas(e.TabPage);
            if (e.TabPage.Name == "tabPageAllTemp")
            {
                ShowAllInk();
                ShowTemparature();
            }
            if (e.TabPage.Name == "tabPageAll")
            {
                ShowAllInk();
            }
            else
            {
                ShowPersonalInk(e.TabPage.Name);
            }
        }
        void com_NewPersonalInkNameReveived(object sender, ComForDisplay.NewPersonalInkNameReceivedEventArgs e)
        {
            //新しいpersonalstroke・・・タブを増やす
            AddMembersTab(e.Name);
        }
        void com_StrokeElementListCreated(object sender, ComForDisplay.StrokeElementListCreatedEventArgs e)
        {
            // 新しいストロークが描かれた --> 自分なら問題ない。そうでないときはタブのハイライトを更新
            UpdateHighlightTab();//e.StrokeElementList);
        }
        void View_ViewChanged(object sender, EventArgs e)
        {
            // 自分の視点が変わった --> タブのハイライトを更新
            UpdateHighlightTab();
        }
        private void MovePanelCanvas(TabPage tp)
        {
            Control c = (Control)Host.Kotodama.EnvironmentTable["Base.Form"];
            Control[] cld = c.Controls.Find("panelCanvas", true);
            Panel pc = (Panel)cld[0];
            pc.Parent.Controls.Remove(pc);
            tp.Controls.Add(pc);
        }
        private void AddMembersTab(string name)
        {
            tabControlMembers.TabPages.Add(name, name);
        }
        private void ShowPersonalInk(string name)
        {
            com.ShowPersonalInkOf(name);
        }
        private void ShowAllInk()
        {
            com.ShowAllInk();
        }
        private void UpdateHighlightTab()
        {
            highlightList.Clear();
            //現在のviewの中のstrokeelementを抽出
            Rectangle view = Host.Kotodama.Presentation.CurrentSlide.View.ViewRectangle;
            FigureElementList fel = Host.Kotodama.Presentation.CurrentSlide.OnScreenElementList;

            //strokeelementのtabでownerがあるものをList<string>にする
            foreach (FigureElement fe in fel)
            {
                if (fe is StrokeElement)
                {
                    string owner = com.GetOwner((StrokeElement)fe);
                    if (owner != "" && !highlightList.Contains(owner)) highlightList.Add(owner);
                }
            }
        }
        bool flag = false;
        private void TickHighlight()
        {
            Control.ControlCollection cld = tabControlMembers.Controls;
            //highlightList.Add(cld[0].Name); //debug
            flag = !flag;
            if (flag)
            {
                //highlightのものだけ、文字列を変更する
                 foreach (Control c in cld)
                {
                    if (c is TabPage)
                    {
                        TabPage tp = (TabPage)c;
                        if (highlightList.Contains(tp.Name))
                        {
                            //tp.ResetText();
                            tp.Text = "*" + tp.Text.Substring(1);
                        }
                    }
                }
            }
            else
            {
                //すべてのtabをリセット
                foreach (Control c in cld)
                {
                    if (c is TabPage)
                    {
                        TabPage tp = (TabPage)c;
                        tp.Text = tp.Name;
                    }
                }
            }
        }
        private void ShowTemparature()
        {
            //全インクを表示する
            //インクを加工する
        }

#endregion

        #region screen系
        void com_ViewMovedReceived(object sender, ComForDisplay.ViewMovedReceivedEventArgs e)
        {
            // 場のスクリーンの表示位置が変わった --> 初めての場合はスクリーンリスト更新。その後スクリーンリストのサムネイルを更新
            AddScreenIfNewName(e.Name, e.ViewRectangle);
            UpdateScreenThumbnail(e.Name, e.ViewRectangle);
        }

        void lvS_SelectedIndexChanged(object sender, EventArgs e)
        {
            // スクリーンリストの選択項目が変わった -->現在のviewをそのスクリーンに映す
            SendCurrentView();
        }
        private void UpdateScreenThumbnail(string name, Rectangle rect)
        {
        }
        private void SendCurrentView()
        {
        }
        private void AddScreenIfNewName(string name, Rectangle rect)
        {
        }

        #endregion
    }
}
